package net.lzzy.practicesapi1.services;

import net.lzzy.practicesapi1.entities.Applicant;
import net.lzzy.practicesapi1.entities.Course;
import net.lzzy.practicesapi1.entities.User;
import net.lzzy.practicesapi1.repositories.ApplicantRepository;
import net.lzzy.practicesapi1.repositories.CourseRepository;
import net.lzzy.practicesapi1.repositories.UserRepository;
import net.lzzy.practicesapi1.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.UUID;


/**
 * @author locker
 */
@Service
public class ApplicantServiceImpl implements ApplicantService{
    private final ApplicantRepository repository;
    private final CourseRepository cRepository;
    private final UserRepository uRepository;

    @Autowired
    public ApplicantServiceImpl(ApplicantRepository repository, CourseRepository cRepository, UserRepository uRepository) {
        this.repository = repository;
        this.cRepository = cRepository;
        this.uRepository = uRepository;
    }

    /**
     * 学生申请注册某课程
     *
     * @param studentId 学生id
     * @param courseId  课程id
     * @param token     token
     * @return 注册完返回注册记录对象
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Applicant apply(UUID studentId, UUID courseId, String token) {
        if (!studentId.toString().equals(JwtUtil.verifyToken(token))){
            return null;
        }
        User student = uRepository.findById(studentId).orElse(null);
        if (student == null){
            return null;
        }
        Course course = cRepository.findById(courseId).orElse(null);
        if (course == null){
            return null;
        }
        Applicant applicant = new Applicant();
        applicant.setCourse(course);
        applicant.setStudent(student);
        applicant.setStatus(Applicant.TYPE_APPLYING);
        return repository.save(applicant);
    }

    /**
     * 获取某学生注册的所有课程
     *
     * @param studentId 学生id
     * @param token     token
     * @return 注册的课程集合
     */
    @Override
    public List<Applicant> getAllCourses(UUID studentId, String token) {
        if (!studentId.toString().equals(JwtUtil.verifyToken(token))){
            return null;
        }
        return repository.findApplicantsByStudentIdEqualsOrderByApplyTimeDesc(studentId);
    }

    /**
     * 获取某学生注册成功的正式课程记录
     *
     * @param studentId 学生id
     * @param token     token
     * @return 注册成功的课程集合
     */
    @Override
    public List<Applicant> getEnrolledCourses(UUID studentId, String token) {
        if (!studentId.toString().equals(JwtUtil.verifyToken(token))){
            return null;
        }
        return repository.findApplicantsByStudentIdEqualsAndStatusEqualsOrderByApplyTimeDesc(studentId, Applicant.TYPE_APPROVED);
    }

    /**
     * 获取某学生申请中的课程记录
     *
     * @param studentId 学生id
     * @param token     token
     * @return 申请中的课程记录
     */
    @Override
    public List<Applicant> getApplyingCourses(UUID studentId, String token) {
        if (!studentId.toString().equals(JwtUtil.verifyToken(token))){
            return null;
        }
        return repository.findApplicantsByStudentIdEqualsAndStatusEqualsOrderByApplyTimeDesc(studentId, Applicant.TYPE_APPLYING);
    }

    /**
     * 获取某学生申请失败的课程记录
     *
     * @param studentId 学生id
     * @param token     token
     * @return 申请失败的课程记录
     */
    @Override
    public List<Applicant> getDeclinedCourses(UUID studentId, String token) {
        if (!studentId.toString().equals(JwtUtil.verifyToken(token))){
            return null;
        }
        return repository.findApplicantsByStudentIdEqualsAndStatusEqualsOrderByApplyTimeDesc(studentId, Applicant.TYPE_DECLINED);
    }

    /**
     * 教师审批课程学习申请
     *
     * @param applicantId 申请记录id
     * @param token       token
     * @return 审批后返回申请记录对象
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Applicant approve(UUID applicantId, String token) {
        Applicant applicant = repository.findById(applicantId).orElse(null);
        if (applicant == null){
            return null;
        }
        Course course = applicant.getCourse();
        UUID teacherId = course.getTeacher().getId();
        if (!teacherId.toString().equals(JwtUtil.verifyToken(token))){
            return null;
        }
        applicant.setStatus(Applicant.TYPE_APPROVED);
        Applicant updated = repository.save(applicant);
        User student = updated.getStudent();
        List<User> students = course.getStudents();
        if (!students.contains(student)){
            students.add(student);
        }
        course.setStudents(students);
        updated.setCourse(cRepository.save(course));
        return updated;
    }

    /**
     * 教师驳回课程申请
     *
     * @param applicantId 申请记录id
     * @param token       token
     * @return 审批后返回的记录对象
     */
    @Override
    public Applicant decline(UUID applicantId, String token) {
        return null;
    }

    /**
     * 获取某课程的所有申请成功的注册记录
     *
     * @param courseId 课程id
     * @param token    token
     * @return 符合条件的课程申请记录
     */
    @Override
    public List<Applicant> getEnrolledStudents(UUID courseId, String token) {
        return null;
    }

    /**
     * 获取某课程申请中的记录
     *
     * @param courseId 课程id
     * @param token    token
     * @return 符合提交的课程申请记录
     */
    @Override
    public List<Applicant> getApplyingStudents(UUID courseId, String token) {
        return null;
    }

    /**
     * 获取某课程已驳回的申请记录
     *
     * @param courseId 课程id
     * @param token    token
     * @return 符合条件的课程申请记录
     */
    @Override
    public List<Applicant> getDeclinedStudents(UUID courseId, String token) {
        return null;
    }

    /**
     * 从课程的正式学生列表中移除某学生
     *
     * @param courseId  课程id
     * @param studentId 要移除的学生id
     * @param token     教师token
     * @return 操作完成后返回新的课程信息给前端
     */
    @Override
    public Course removeStudent(UUID courseId, UUID studentId, String token) {
        return null;
    }
}
